package com.hfzy.ihk.common.util;

import com.google.common.collect.Lists;
import com.hfzy.ihk.common.util.date.DateUtils;
import org.springframework.util.ReflectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 通用工具类(提供一些常用而不好归类的方法)
 * 
 * @author healy
 * 
 */
public class CommonUtils {
	public static final String SYSPROP_RUNMODE = "runMode";
	public static final String SYSPROP_RUNMODE_TEST = "test";
	public static final String SYSPROP_TESTMODE = "testMode";
	public static final String SYSPROP_TESTMODE_ON = "on";

	/**
	 * 获取16个字符的唯一号
	 * 
	 * @return
	 */
	public static String getUUID() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	public static Object newInstance(String className) {
		try {
			return Class.forName(className).newInstance();
		} catch (Exception e) {
			throw new RuntimeException("new instance fail : " + e.getMessage(),
					e);
		}
	}

	public boolean isTestMode() {
		return SYSPROP_RUNMODE_TEST.equals(System.getProperty(SYSPROP_RUNMODE));
	}

	public boolean isTestMode(String funcName) {
		if (isTestMode()) {
			return true;
		}
		return SYSPROP_TESTMODE_ON.equals(System.getProperty(SYSPROP_TESTMODE
				+ "." + funcName));
	}
	
	public static <T> T getEnum(Class<T> clazz,int index){  
		   T[] c=clazz.getEnumConstants();  
			    return c[index];  
	}

	/**
	 * 获取服务器地址
	 *
	 127.0.0.1
	 0:0:0:0:0:0:0:1
	 2001:0:9d38:6ab8:30a2:b970:48c0:b30d
	 fe80:0:0:0:30a2:b970:48c0:b30d%11
	 fe80:0:0:0:0:5efe:ac10:638%13
	 172.16.6.56
	 fe80:0:0:0:dd38:33c9:c74e:2612%14
	 * */
	public static List<String> getServerAddresses() {
		try {
			List<String> ret = new ArrayList<String>();
			Enumeration<NetworkInterface> nis = NetworkInterface
					.getNetworkInterfaces();
			while (nis.hasMoreElements()) {
				NetworkInterface ni = nis.nextElement();
				Enumeration<InetAddress> ias = ni.getInetAddresses();
				while (ias.hasMoreElements()) {
					InetAddress ia = ias.nextElement();
					ret.add(ia.getHostAddress());
				}
			}
			return ret;
		} catch (Exception ex) {
			return new ArrayList<String>();
		}
	}

	/**
	 *
	 从下面的几个address,找出172.16.6.56，使用字符串匹配
	 127.0.0.1
	 0:0:0:0:0:0:0:1
	 2001:0:9d38:6ab8:30a2:b970:48c0:b30d
	 fe80:0:0:0:30a2:b970:48c0:b30d%11
	 fe80:0:0:0:0:5efe:ac10:638%13
	 172.16.6.56
	 fe80:0:0:0:dd38:33c9:c74e:2612%14
	 * */
	public static String getServerIp(){
		List<String> address = getServerAddresses();
		String ip = null;

		for(String s : address){
			String regex = "\\d+\\.\\d+\\.\\d+\\.\\d+";
			Pattern p = Pattern.compile(regex);
			Matcher m = p.matcher(s);
			if(m.find()) {
				ip = m.group();
				System.out.println("this server ip :"+ip);
				if(!ip.startsWith("127")){
					break;
				}
			}
		}
		return ip;
	}

	public static String getInputStr(HttpServletRequest request)
	{
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		String line = null;
		StringBuilder sb = new StringBuilder();
		try {
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		return sb.toString();
	}
	/**
	 * 根据前缀+ip截取后面两位来定义name
	 * */
	public static String getServerName(){

		String ip = getServerIp();
		String temp = ip.substring(ip.indexOf(".")+1);
		temp = temp.substring(temp.indexOf(".")+1);

		return "web-"+temp.replace(".","-"); //取IP最后一个数
	}

	/**
	 * 从数组中随机一个元素
	 * */
	public static Integer randomArray(final Integer[] array,final  Integer arrayLength){
		return array[ThreadLocalRandom.current().nextInt(arrayLength)];
	}

	/**
	 * 从列表中随机一个元素
	 * */
	public static Object randomList(final List list,final  Integer listSize){
		return list.get(ThreadLocalRandom.current().nextInt(listSize));
	}
	/**
	 * 从列表中随机一个元素
	 * */
	public static Integer randomList(final CopyOnWriteArrayList<Integer> list, final  Integer listSize){
		return list.get(ThreadLocalRandom.current().nextInt(listSize));
	}

	public static Integer randomInt(Integer range){
		Random r = new Random();
		return r.nextInt(range);
	}

	/**
	 * 6位随机数
	 *
	 * @return
	 */
	public static String sixRandom() {
		int n = 10;
		Random rand = new Random();
		boolean[] bool = new boolean[n];
		int randInt = 0;
		StringBuffer str = new StringBuffer();
		for (int i = 0; i < 6; i++) {
			do {
				randInt = rand.nextInt(n);
			} while (bool[randInt]);
			bool[randInt] = true;
			str.append(randInt);
		}
		return str.toString();
	}

	/**
	 * 把 , ; 变为 ，；
	 *
	 * @param str
	 * @return
	 */
	public static String replStr(String str) {
		str = str.replaceAll(",", "，");
		str = str.replaceAll(";", "；");
		return str.toString();
	}

	/**
	 * 把 String 转为 字符流
	 *
	 * @param s
	 * @return
	 */
	public static InputStream getStringInputStream(String s) {
		if (s != null && !s.equals("")) {
			try {
				ByteArrayInputStream stringInputStream = new ByteArrayInputStream(
						s.getBytes());
				return stringInputStream;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * 获取mac
	 * */
	public static String getMac() {
		String mac = null;
		String os = System.getProperty("os.name").toLowerCase();
		if(os.startsWith("windows")) {
			try {
				Process pro = Runtime.getRuntime().exec("cmd.exe /c ipconfig/all");

				InputStream is = pro.getInputStream();
				BufferedReader br = new BufferedReader(new InputStreamReader(is,"GB2312"));
				String message = br.readLine();



				int index = -1;
				while (message != null) {

					//物理地址. . . . . . . . . . . . . : D4-3D-7E-BA-44-02
					if ((index = message.indexOf("Physical Address")) > 0 || (index = message.indexOf("物理地址")) > 0) {
//						mac = message.substring(index + 32).trim();
						int lastIdx = message.lastIndexOf(":");
						mac = message.substring(lastIdx+1);
						mac = mac.trim();
						break;
					}
					message = br.readLine();
//					System.out.println("msg:"+message);
				}

				br.close();
				pro.destroy();
			} catch (IOException e) {
				System.out.println("Can't get mac address!");
				e.printStackTrace();
			}
		} else if(os.startsWith("linux")) {
			try {
				Process pro = Runtime.getRuntime().exec("/bin/sh -c ifconfig -a");

				InputStream is = pro.getInputStream();
				BufferedReader br = new BufferedReader(new InputStreamReader(is, "GB2312"));
				String message = null;

				Pattern pattern = Pattern.compile("\\b\\w+:\\w+:\\w+:\\w+:\\w+:\\w+\\b");
				Matcher matcher;

				while ((message = br.readLine()) != null) {
					matcher = pattern.matcher(message);
					if (matcher.find()) {
						mac = matcher.group();
						break;
					}
				}
			} catch (IOException e) {
				System.out.println("Can't get mac address!");
				e.printStackTrace();
			}
		}

		if(mac != null) {
			mac = mac.replaceAll("-", ":").toUpperCase();
		}

		return mac;
	}

	/*执行命令，返回内容*/
	public static String execCommand(String command){

		if(command == null || command =="")
			return "false";

		InputStream is = null;
		StringBuffer sb = new StringBuffer();
		try {
			// 运行环境
			Runtime rt = Runtime.getRuntime();
//			String command = "net start jenkinsslave-D__JavaSolution_Jenkins";
			Process proc = rt.exec(command);
			proc.waitFor(60000, TimeUnit.MILLISECONDS);
			is = proc.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is,"GB2312"));
			String line = null;

			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

//			System.out.println("结果："+ (sb.toString().indexOf("启动成功") != -1));
			is.close();
			br.close();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (is != null)
					is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return sb.toString();
	}

	public static String execCommand1(String command){

		if(command == null || command =="")
			return "false";

		InputStream is = null;
		StringBuffer sb = new StringBuffer();
		try {
			// 运行环境
			Runtime rt = Runtime.getRuntime();
			Process proc = rt.exec(command);


			//获取进程的标准输入流
			final InputStream is1 = proc.getInputStream();
			//获取进城的错误流
			final InputStream is2 = proc.getErrorStream();

		//	is = proc.getInputStream();

			new Thread() {
				public void run() {
					try {
					BufferedReader br1 = new BufferedReader(new InputStreamReader(is1,"GB2312"));

						String line1 = null;
						while ((line1 = br1.readLine()) != null) {
							if (line1 != null){}
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
					finally{
						try {
							is1.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}.start();

			new Thread() {
				public void  run() {
					BufferedReader br2 = new  BufferedReader(new  InputStreamReader(is2));
					try {
						String line2 = null ;
						while ((line2 = br2.readLine()) !=  null ) {
							if (line2 != null){}
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
					finally{
						try {
							is2.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}.start();

			proc.waitFor(60000, TimeUnit.MILLISECONDS);
			proc.destroy();
//			BufferedReader br = new BufferedReader(new InputStreamReader(is,"GB2312"));
//			String line = null;
//
//			while ((line = br.readLine()) != null) {
//				System.out.println(line);
//				sb.append(line);
//			}
//			is.close();
//			br.close();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {

			try {
				if (is != null)
					is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return sb.toString();
	}

	/*public static void main(String[] arguments) throws Exception{
		System.out.println("ip ......... "+getServerIp());
		System.out.println("MAC is -> "+getMac());
	}*/

	public static boolean objectEquals(Object obj1,Object obj2){
		if(obj1==null&&obj2==null){
			return true;
		}
		if((obj1==null&&obj2!=null)||(obj1!=null&&obj2==null)){
			return false;
		}
		return obj1.equals(obj2);
	}

	public static boolean listObjectEquals(List<?> list1,List<?> list2){
		if(list1==null&&list2==null){
			return true;
		}
		if((list1==null&&list2!=null)||(list1!=null&&list2==null)){
			return false;
		}
		if(list1.size()!=list2.size()){
			return false;
		}
		Iterator<?> iter = list1.iterator();
		while (iter.hasNext()){
			if(!list2.contains(iter.next())){
				return false;
			}
		}
		return true;
	}

	/**
	 * 判断两个对象哪些值不一样
	 * @param oldObj 旧数据对象
	 * @param newObj 新数据对象
	 * @param ignoreArr 不包含的字段
	 * @param containArr 包含的字段
	 * @return 返回修改过后的新值
	 * @throws Exception
	 */
	public static Map<String, Object> compareObj(Object oldObj,Object newObj,List<String> ignoreArr,List<String> containArr)throws Exception{
		List<String> ojbTypeList = Arrays.asList("java.lang.Integer",
				"java.lang.Double",
				"java.lang.Float",
				"java.lang.Long",
				"java.lang.Short",
				"java.lang.Byte",
				"java.lang.Boolean",
				"java.lang.Character",
				"java.lang.String",
				"java.lang.Integer");
		List<String> typeList = Arrays.asList("int","double","long","short","byte","boolean","char","float");
		Map<String, Object> result = new HashMap<String, Object>();
		if(oldObj.getClass()==newObj.getClass()){
			Field[] fs = oldObj.getClass().getDeclaredFields();
			for (Field field  : fs) {
				String fieldName = field.getName();
				//不包含的
				if(ignoreArr!=null&&ignoreArr.contains(fieldName)){
					continue;
				}
				//包含的
				if(containArr!=null&&!containArr.contains(fieldName)){
					continue;
				}
				PropertyDescriptor pd = new PropertyDescriptor(fieldName, oldObj.getClass());
				Method readMethod = pd.getReadMethod();// get方法
				// 在obj1上调用get方法等同于获得obj1的属性值
				Object o1 = readMethod.invoke(oldObj);
				// 在obj2上调用get方法等同于获得obj2的属性值
				Object o2 = readMethod.invoke(newObj);
				Class<?> fieldType = pd.getPropertyType();
				//判断是否是对象类型或者枚举类型
				if(ojbTypeList.contains(fieldType.getName())||fieldType.isEnum()){
					if(!objectEquals(o1,o2)){
						result.put(fieldName,o2);
					}
				//判断是否是基本类型
				}else if(typeList.contains(fieldType.getName())){
					if(o1!=o2){
						result.put(fieldName,o2);
					}
				}else if("java.util.Date".equals(fieldType.getName())){
					Date date1 = (Date)o1;
					Date date2 = (Date)o2;
					long time1 = 0;
					long time2 = 0;
					if(date1!=null){time1 = date1.getTime();}
					if(date2!=null){time2 = date2.getTime();}
					if(time1!=time2){
						result.put(fieldName,date2);
					}
				}else if("java.util.List".equals(fieldType.getName())){
					ParameterizedType pt = (ParameterizedType) field.getGenericType();
					Class clz = (Class) pt.getActualTypeArguments()[0];
					if(clz==null){
						continue;
					}
					if(ojbTypeList.contains(clz.getName())||clz.isEnum()){
						if(!listObjectEquals((List<?>)o1,(List<?>)o2)){
							result.put(fieldName,o2);
						}
					}
				}
			}
		}
		return result;
	}

	/**
	 * 根据反射set值
	 * @param obj
	 * @param name
	 * @param value
	 * @throws Exception
	 */
	public static void setObjName(Object obj,String name,Object value)throws Exception{
		Field field = obj.getClass().getDeclaredField(name);
		PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
		Class<?> fieldType = pd.getPropertyType();
		switch (fieldType.getName()){
			case "java.lang.Integer":case "int":
				value = Integer.valueOf(value.toString());
				break;
			case "java.lang.Double":case "double":
				value = Double.valueOf(value.toString());
				break;
			case "java.lang.Float":case "float":
				value = Float.valueOf(value.toString());
				break;
			case "java.lang.Long":case "long":
				value = Long.valueOf(value.toString());
				break;
			case "java.lang.Short":case "short":
				value = Short.valueOf(value.toString());
				break;
			case "java.lang.Byte":case "byte":
				value = Byte.valueOf(value.toString());
				break;
			case "java.lang.Boolean":case "boolean":
				value = Boolean.valueOf(value.toString());
				break;
			case "java.lang.Character":case "char":
				value = Character.valueOf((Character) value);
				break;
			case "java.lang.String":
				value = value.toString();
				break;
			case "java.util.Date":
				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
				SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmss");
				value = sdf1.parse(sdf1.format(sdf.parse(value.toString())));
				break;
			case "java.util.List":
				ParameterizedType pt = (ParameterizedType) field.getGenericType();
				Class clz = (Class) pt.getActualTypeArguments()[0];
				if(clz==null){
					break;
				}
				switch (clz.getName()){
					case "java.lang.Integer":
						value = (List<Integer>) value;
						break;
					case "java.lang.Double":
						value = (List<Double>) value;
						break;
					case "java.lang.Float":
						value = (List<Float>) value;
						break;
					case "java.lang.Long":
						value = (List<Long>) value;
						break;
					case "java.lang.Short":
						value = (List<Short>) value;
						break;
					case "java.lang.Byte":
						value = (List<Byte>) value;
						break;
					case "java.lang.Boolean":
						value = (List<Boolean>) value;
						break;
					case "java.lang.Character":
						value = (List<Character>) value;
						break;
					case "java.lang.String":
						value = (List<String>) value;
						break;
					default:break;
				}
				default:break;
		}
		if(fieldType.isEnum()){
			Method valueOfMethod = pd.getPropertyType().getMethod("fromValue",String.class);
			//ReflectionUtils.invokeMethod();
			value = valueOfMethod.invoke(null,value.toString());
		}
		Method setMethod = pd.getWriteMethod();
		setMethod.invoke(obj,value);
	}

	/**
	 * obj转map
	 * @param obj
	 * @param ignoreArr
	 * @param isNull
	 * @return
	 */
	public static Map<String, Object> objectMap(Object obj,List<String> ignoreArr,List<String> containArr,Boolean isNull) {
		Map<String, Object> map = new HashMap<>();
		if (obj == null) {
			return map;
		}
		Class clazz = obj.getClass();
		Field[] fields = clazz.getDeclaredFields();
		try {
			for (Field field : fields) {
				String fieldName = field.getName();
				//不包含的
				if(ignoreArr!=null&&ignoreArr.contains(fieldName)){
					continue;
				}
				//包含的
				if(containArr!=null&&!containArr.contains(fieldName)){
					continue;
				}
				field.setAccessible(true);
				if(isNull){
					map.put(field.getName(), field.get(obj));
				}else{
					if(field.get(obj)!=null&&!"NULL".equals(field.get(obj))&&!"null".equals(field.get(obj))){
						map.put(field.getName(), field.get(obj));
					}
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}

}
